from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File as FastAPIFile, Form
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from typing import List, Optional
import os
import shutil
import uuid
import hashlib
from datetime import datetime

from ..core.database import get_db
from ..models import File, FileType, User, FolderDepartmentPermission, FolderUserPermission, FileVersion
from ..api.auth import get_current_user
from ..schemas.file import FileInfo, FileCreate, FolderCreate
from ..core.config import settings
from ..core.permissions import (
    can_access_folder, can_access_file, get_folder_level,
    check_folder_operation_permission, check_file_operation_permission
)

router = APIRouter()

@router.get("/", response_model=List[FileInfo])
async def list_files(
    parent_id: Optional[int] = None,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取文件列表"""
    # 检查父文件夹访问权限
    if parent_id:
        if not check_folder_operation_permission(parent_id, current_user, "read", db):
            raise HTTPException(status_code=403, detail="没有权限访问此文件夹")
    
    query = db.query(File).filter(
        File.is_deleted == False,
        File.parent_id == parent_id
    )
    
    files = query.all()
    accessible_files = []
    
    for file in files:
        if file.file_type == FileType.FOLDER:
            can_read, _, _ = can_access_folder(file, current_user, db)
        else:
            can_read, _, _ = can_access_file(file, current_user, db)
        
        if can_read:
            accessible_files.append(FileInfo(
                id=file.id,
                name=file.name,
                file_type=file.file_type.value,
                size=file.size,
                mime_type=file.mime_type,
                parent_id=file.parent_id,
                owner_id=file.owner_id,
                level=get_folder_level(file, db) if file.file_type == FileType.FOLDER else 0,
                share_level=file.share_level,
                description=file.description or "",
                tags=file.tags or "",
                created_at=file.created_at,
                updated_at=file.updated_at
            ))
    
    return accessible_files

@router.post("/folder", response_model=FileInfo)
async def create_folder(
    folder_data: FolderCreate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """创建文件夹"""
    # 检查权限：在父文件夹中创建子文件夹
    if not check_folder_operation_permission(folder_data.parent_id, current_user, "create", db):
        raise HTTPException(status_code=403, detail="没有权限在此位置创建文件夹")
    
    # 计算新文件夹的层级
    folder_level = 0
    if folder_data.parent_id:
        parent = db.query(File).filter(
            File.id == folder_data.parent_id,
            File.file_type == FileType.FOLDER,
            File.is_deleted == False
        ).first()
        if not parent:
            raise HTTPException(status_code=404, detail="父文件夹不存在")
        
        folder_level = get_folder_level(parent, db) + 1
        folder_path = os.path.join(parent.path, folder_data.name)
        
        # 检查层级限制：第一级和第二级文件夹仅管理员可创建
        if folder_level <= 1 and current_user.role.value != "admin":
            raise HTTPException(status_code=403, detail="只有管理员可以创建第一级和第二级文件夹")
    else:
        # 根目录只有管理员可以创建文件夹
        if current_user.role.value != "admin":
            raise HTTPException(status_code=403, detail="只有管理员可以在根目录创建文件夹")
        folder_path = os.path.join(settings.UPLOAD_DIR, str(current_user.id), folder_data.name)
    
    # 创建物理文件夹
    os.makedirs(folder_path, exist_ok=True)
    
    # 创建数据库记录
    new_folder = File(
        name=folder_data.name,
        file_type=FileType.FOLDER,
        path=folder_path,
        parent_id=folder_data.parent_id,
        owner_id=current_user.id,
        department_id=current_user.department_id,
        level=folder_level,
        share_level="private",  # 默认私有
        description=folder_data.description or "",
        tags=folder_data.tags or ""
    )
    
    db.add(new_folder)
    db.commit()
    db.refresh(new_folder)
    
    return FileInfo(
        id=new_folder.id,
        name=new_folder.name,
        file_type=new_folder.file_type.value,
        size=new_folder.size,
        mime_type=new_folder.mime_type,
        parent_id=new_folder.parent_id,
        owner_id=new_folder.owner_id,
        level=new_folder.level,
        share_level=new_folder.share_level,
        description=new_folder.description,
        tags=new_folder.tags,
        created_at=new_folder.created_at,
        updated_at=new_folder.updated_at
    )

@router.post("/upload", response_model=FileInfo)
async def upload_file(
    file: UploadFile = FastAPIFile(...),
    parent_id: Optional[int] = Form(None),
    share_level: str = Form("private"),
    description: str = Form(""),
    tags: str = Form(""),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """上传文件"""
    # 检查权限：在父文件夹中上传文件
    if not check_folder_operation_permission(parent_id, current_user, "create", db):
        raise HTTPException(status_code=403, detail="没有权限在此位置上传文件")
    
    # 检查文件大小
    if file.size > settings.MAX_FILE_SIZE:
        raise HTTPException(status_code=413, detail="文件太大")
    
    # 检查文件扩展名
    file_ext = os.path.splitext(file.filename)[1].lower()
    if file_ext not in settings.ALLOWED_EXTENSIONS:
        raise HTTPException(status_code=400, detail="不支持的文件类型")
    
    # 确定上传路径
    if parent_id:
        parent = db.query(File).filter(
            File.id == parent_id,
            File.file_type == FileType.FOLDER,
            File.is_deleted == False
        ).first()
        if not parent:
            raise HTTPException(status_code=404, detail="父文件夹不存在")
        upload_dir = parent.path
    else:
        upload_dir = os.path.join(settings.UPLOAD_DIR, str(current_user.id))
        os.makedirs(upload_dir, exist_ok=True)
    
    # 生成唯一文件名
    unique_filename = f"{uuid.uuid4()}_{file.filename}"
    file_path = os.path.join(upload_dir, unique_filename)
    
    # 保存文件并计算校验和
    file_content = file.file.read()
    file.file.seek(0)  # 重置文件指针
    
    # 计算文件的MD5校验和
    checksum = hashlib.md5(file_content).hexdigest()
    
    with open(file_path, "wb") as buffer:
        buffer.write(file_content)
    
    # 创建数据库记录
    new_file = File(
        name=file.filename,
        file_type=FileType.FILE,
        path=file_path,
        size=file.size,
        mime_type=file.content_type,
        parent_id=parent_id,
        owner_id=current_user.id,
        department_id=current_user.department_id,
        level=0,  # 文件层级为0
        share_level=share_level,
        description=description,
        tags=tags
    )
    
    db.add(new_file)
    db.commit()
    db.refresh(new_file)
    
    # 创建第一个版本
    first_version = FileVersion(
        file_id=new_file.id,
        version_number=1,
        path=file_path,
        size=file.size,
        mime_type=file.content_type,
        checksum=checksum,
        comment="初始版本",
        created_by=current_user.id,
        is_current=True
    )
    
    db.add(first_version)
    db.commit()
    
    return FileInfo(
        id=new_file.id,
        name=new_file.name,
        file_type=new_file.file_type.value,
        size=new_file.size,
        mime_type=new_file.mime_type,
        parent_id=new_file.parent_id,
        owner_id=new_file.owner_id,
        level=new_file.level,
        share_level=new_file.share_level,
        description=new_file.description,
        tags=new_file.tags,
        created_at=new_file.created_at,
        updated_at=new_file.updated_at
    )

@router.get("/{file_id}/download")
async def download_file(
    file_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """下载文件"""
    file = db.query(File).filter(
        File.id == file_id,
        File.file_type == FileType.FILE,
        File.is_deleted == False
    ).first()
    
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if not can_access_file(file, current_user, db):
        raise HTTPException(status_code=403, detail="没有权限访问此文件")
    
    if not os.path.exists(file.path):
        raise HTTPException(status_code=404, detail="文件不存在")
    
    return FileResponse(
        path=file.path,
        filename=file.name,
        media_type=file.mime_type or 'application/octet-stream'
    )

@router.delete("/{file_id}")
async def delete_file(
    file_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """删除文件或文件夹"""
    file = db.query(File).filter(File.id == file_id).first()
    
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if file.file_type == FileType.FOLDER:
        if not check_folder_operation_permission(file.id, current_user, "delete", db):
            raise HTTPException(status_code=403, detail="没有权限删除此文件夹")
        
        # 检查层级限制：第一级和第二级文件夹仅管理员可删除
        if file.level is not None and file.level <= 1 and current_user.role.value != "admin":
            raise HTTPException(status_code=403, detail="只有管理员可以删除第一级和第二级文件夹")
    else:
        if not check_file_operation_permission(file.id, current_user, "delete", db):
            raise HTTPException(status_code=403, detail="没有权限删除此文件")
    
    # 标记为已删除
    file.is_deleted = True
    db.commit()
    
    return {"message": "文件删除成功"}

@router.put("/{file_id}/rename")
async def rename_file(
    file_id: int,
    new_name: str = Form(...),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """重命名文件或文件夹"""
    file = db.query(File).filter(
        File.id == file_id,
        File.is_deleted == False
    ).first()
    
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if file.file_type == FileType.FOLDER:
        if not check_folder_operation_permission(file.id, current_user, "write", db):
            raise HTTPException(status_code=403, detail="没有权限重命名此文件夹")
        
        # 检查层级限制：第一级和第二级文件夹仅管理员可重命名
        if file.level is not None and file.level <= 1 and current_user.role.value != "admin":
            raise HTTPException(status_code=403, detail="只有管理员可以重命名第一级和第二级文件夹")
    else:
        if not check_file_operation_permission(file.id, current_user, "write", db):
            raise HTTPException(status_code=403, detail="没有权限重命名此文件")
    
    # 更新文件名
    file.name = new_name
    file.updated_at = datetime.utcnow()
    db.commit()
    
    return {"message": "重命名成功"}

@router.get("/shared", response_model=dict)
async def get_shared_files(
    page: int = 1,
    page_size: int = 20,
    share_level: Optional[str] = None,
    type: Optional[str] = None,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取共享文件列表"""
    # 基础查询：获取非私有的文件和文件夹
    query = db.query(File).filter(
        File.is_deleted == False,
        File.share_level != "private"
    )
    
    # 根据用户权限过滤
    if current_user.role.value != "admin":
        # 非管理员只能看到：
        # 1. 公开共享的文件
        # 2. 部门共享且属于同一部门的文件
        # 3. 有特定权限的文件夹
        from sqlalchemy import or_, and_
        
        accessible_conditions = [
            File.share_level == "public",  # 公开文件
        ]
        
        # 部门共享文件（同部门）
        if current_user.department_id:
            accessible_conditions.append(
                and_(
                    File.share_level == "department",
                    File.department_id == current_user.department_id
                )
            )
        
        # 有特定权限的文件夹
        folder_permissions = db.query(FolderUserPermission.folder_id).filter(
            FolderUserPermission.user_id == current_user.id
        ).subquery()
        
        accessible_conditions.append(
            File.id.in_(folder_permissions)
        )
        
        # 有部门权限的文件夹
        if current_user.department_id:
            dept_permissions = db.query(FolderDepartmentPermission.folder_id).filter(
                FolderDepartmentPermission.department_id == current_user.department_id
            ).subquery()
            
            accessible_conditions.append(
                File.id.in_(dept_permissions)
            )
        
        query = query.filter(or_(*accessible_conditions))
    
    # 应用筛选条件
    if share_level:
        query = query.filter(File.share_level == share_level)
    
    if type:
        if type == "folder":
            query = query.filter(File.file_type == FileType.FOLDER)
        elif type == "file":
            query = query.filter(File.file_type == FileType.FILE)
    
    # 计算总数
    total = query.count()
    
    # 分页
    offset = (page - 1) * page_size
    files = query.offset(offset).limit(page_size).all()
    
    # 构建返回数据
    file_list = []
    for file in files:
        # 获取所有者信息
        owner = db.query(User).filter(User.id == file.owner_id).first()
        owner_name = owner.full_name if owner else "未知用户"
        
        file_info = {
            "id": file.id,
            "name": file.name,
            "is_folder": file.file_type == FileType.FOLDER,
            "size": file.size,
            "mime_type": file.mime_type,
            "parent_id": file.parent_id,
            "owner_id": file.owner_id,
            "owner_name": owner_name,
            "department_id": file.department_id,
            "level": file.level,
            "share_level": file.share_level,
            "description": file.description or "",
            "tags": file.tags or "",
            "created_at": file.created_at,
            "updated_at": file.updated_at
        }
        file_list.append(file_info)
    
    return {
        "files": file_list,
        "total": total,
        "page": page,
        "page_size": page_size,
        "pages": (total + page_size - 1) // page_size
    }

@router.put("/{file_id}/metadata", response_model=FileInfo)
async def update_file_metadata(
    file_id: int,
    description: str = Form(""),
    tags: str = Form(""),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """更新文件或文件夹的描述和标签"""
    file = db.query(File).filter(
        File.id == file_id,
        File.is_deleted == False
    ).first()
    
    if not file:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    # 检查权限
    if file.file_type == FileType.FOLDER:
        if not check_folder_operation_permission(file.id, current_user, "write", db):
            raise HTTPException(status_code=403, detail="没有权限修改此文件夹信息")
    else:
        if not check_file_operation_permission(file.id, current_user, "write", db):
            raise HTTPException(status_code=403, detail="没有权限修改此文件信息")
    
    # 更新描述和标签
    file.description = description
    file.tags = tags
    file.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(file)
    
    return FileInfo(
        id=file.id,
        name=file.name,
        file_type=file.file_type.value,
        size=file.size,
        mime_type=file.mime_type,
        parent_id=file.parent_id,
        owner_id=file.owner_id,
        level=file.level,
        share_level=file.share_level,
        description=file.description,
        tags=file.tags,
        created_at=file.created_at,
        updated_at=file.updated_at
    )

@router.get("/search", response_model=dict)
async def search_files(
    q: str,
    page: int = 1,
    page_size: int = 20,
    search_in: str = "all",  # all, name, description, tags
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """搜索文件和文件夹"""
    from sqlalchemy import or_, and_
    
    # 基础查询
    query = db.query(File).filter(File.is_deleted == False)
    
    # 构建搜索条件
    search_conditions = []
    
    if search_in in ["all", "name"]:
        search_conditions.append(File.name.contains(q))
    
    if search_in in ["all", "description"]:
        search_conditions.append(File.description.contains(q))
    
    if search_in in ["all", "tags"]:
        search_conditions.append(File.tags.contains(q))
    
    if search_conditions:
        query = query.filter(or_(*search_conditions))
    
    # 权限过滤：只返回用户有权限访问的文件
    accessible_files = []
    files = query.all()
    
    for file in files:
        if file.file_type == FileType.FOLDER:
            can_read, _, _ = can_access_folder(file, current_user, db)
        else:
            can_read, _, _ = can_access_file(file, current_user, db)
        
        if can_read:
            accessible_files.append(file)
    
    # 分页
    total = len(accessible_files)
    offset = (page - 1) * page_size
    paginated_files = accessible_files[offset:offset + page_size]
    
    # 构建返回数据
    file_list = []
    for file in paginated_files:
        file_info = FileInfo(
            id=file.id,
            name=file.name,
            file_type=file.file_type.value,
            size=file.size,
            mime_type=file.mime_type,
            parent_id=file.parent_id,
            owner_id=file.owner_id,
            level=get_folder_level(file, db) if file.file_type == FileType.FOLDER else 0,
            share_level=file.share_level,
            description=file.description or "",
            tags=file.tags or "",
            created_at=file.created_at,
            updated_at=file.updated_at
        )
        file_list.append(file_info)
    
    return {
        "files": file_list,
        "total": total,
        "page": page,
        "page_size": page_size,
        "pages": (total + page_size - 1) // page_size,
        "query": q,
        "search_in": search_in
    }